<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { merge } from 'lodash-es'
import { useRoute } from 'vue-router'
import { somConfig } from '../../config'
import type { ICaseTableItem } from '../../type'
import { runCase, updateCase } from '@/api/cases'
import { heatBaseOptions } from '@/components/ui/chart/src/heatOptions'
import useStore from '@/stores'
import { useFetch } from '@/composables/useFetch'
import { hvTransformArray, isEmptyObject } from '@/utils'
import { useCaseResult } from '@/views/cases/components/useCaseResult'

const route = useRoute()
const { cases } = useStore()
const caseInfo = computed(() => cases.caseInfo)
const detailData = computed(() => caseInfo.value?.jsonArgs ? JSON.parse(caseInfo.value?.jsonArgs) : null)
const somFormRef = ref()
const heatRawOptions = ref(heatBaseOptions)
const heat2DOptions = ref(heatBaseOptions)
const varName = ref()
const varNameOptions = ref()
const chartWidth = ref('450px')
const chartHeight = ref('450px')
const clusterName = ref()
const clusterOptions = ref<{ label: string, value: any }[]>([])
function changeChartSize() {
  // 保持正方形小方块
  const { map_l, map_w } = somFormRef.value?.model
  let width = 450
  let height = 450
  if (map_l > map_w)
    height = map_l / map_w * 450
  else
    width = map_w / map_l * 450

  chartWidth.value = `${width}px`
  chartHeight.value = `${height}px`
}

const { loading: runLoading, execute: runCaseExecute } = useFetch((parmas: any = {}) => runCase(parmas))
const { execute: updateCaseExecute } = useFetch((parmas: ICaseTableItem) => updateCase(parmas))

// 获取结果
const { somResult, somRawLoading, onClickRefreshAllAction } = useCaseResult()
watch(() => somResult.value, () => {
  if (isEmptyObject(somResult.value)) {
    heatRawOptions.value = heat2DOptions.value = heatBaseOptions
    return
  }

  const data = Object.keys(somResult.value?.som_somproj)
  const options = data.map((item: any) => {
    return {
      label: item,
      value: item,
    }
  })
  clusterOptions.value = options
  clusterName.value = clusterOptions.value[0].label

  heatRawOptions.value = _setChartOption(somResult.value?.som_heatmap)
  onClickChangeHeatmap('SOM_raw')
  onClickClusterName(clusterName.value)
}, { deep: true })

// 共用一个按钮加载状态
watch(() => runLoading.value, (val: boolean) => {
  cases.setCaseRunLoading(val)
})

// 保存表单信息
watch(() => somFormRef.value?.model, () => {
  cases.initFormInfoSkip()
  const formInfo = Object.assign({}, cases.formInfo, { SOM: { ...somFormRef.value.model, skip: false } })
  cases.saveFormInfo(formInfo)
}, { deep: true })

// 接口的表单字段有变化需要重新回填表单
watch(() => detailData.value?.SOM, (nVal: any) => {
  if (nVal)
    initForm()
}, { deep: true })

onMounted(() => {
  initForm()
})

onBeforeUnmount(() => {
  somResult.value = null as any
  heatRawOptions.value = heat2DOptions.value = null as any
  varName.value = varNameOptions.value = null as any
})

function initForm() {
  if (detailData.value && !isEmptyObject(detailData.value)) {
    somFormRef.value.model = detailData.value.SOM
    changeChartSize()
  }
}

function onClickSubmitRun() {
  const validate = somFormRef.value.validate()

  validate().then(async () => {
    // 后端进行缓存全量参数
    await updateCaseExecute({ caseId: route.query.id, jsonArgs: JSON.stringify(cases.formInfo) })

    await runCaseExecute({ caseId: route.query.id })
  })
}

async function onClickChangeHeatmap(name: string) {
  const { som_heatmap_keys, som_heatmap_dict } = somResult.value
  const heatmapResult = som_heatmap_dict && som_heatmap_dict[name]
  // 选择第一个
  clusterName.value = clusterOptions.value[0].label
  const clusterData = somResult.value?.som_somproj[clusterOptions.value[0].label]
  const options = _setChartOption(heatmapResult, clusterData)
  heat2DOptions.value = options
  varName.value = name
  varNameOptions.value = som_heatmap_keys.map((item: any) => {
    return {
      value: item,
      label: item,
    }
  })
}

async function onClickClusterName(name: string) {
  const clusterData = somResult.value?.som_somproj[name]
  const options = _setChartOption(somResult.value?.som_heatmap, clusterData)
  heat2DOptions.value = options
}

function _setChartOption(resultData: any, pointerData?: any) {
  const { data, z_min, z_max, var_name } = resultData
  const transformCluster = pointerData ? hvTransformArray(pointerData) : null

  const options = merge(
    {},
    heatBaseOptions,
    {
      // grid: { right: '80px' },
      xAxis: {
        name: 'Width',
        nameLocation: 'center',
        nameTextStyle: {
          lineHeight: 50,
        },
      },
      yAxis: { name: 'Height' },
      visualMap: {
        min: z_min,
        max: z_max,
        top: 'center', // 垂直居中
        right: 0, // 距离左边的距离
        text: [z_max, z_min],
        // splitNumber: 8,
        // type: 'piecewise',
        inRange: {
          color: [
            '#000094',
            '#0000fc',
            '#005cff',
            '#00c0ff',
            '#26ffda',
            '#8eff72',
            '#eeff12',
            '#ffac00',
            '#ff4800',
            '#e40000',
          ],
        },
      },
      label: {
        show: true,
        formatter(parmas: any) {
          const [x, y] = parmas.data
          return transformCluster && transformCluster[x][y] === 1 ? 'O' : ''
        },
      },
      series: [
        {
          name: var_name,
          data,
        },
      ],
    },
  )
  return options
}

defineExpose({ onClickSubmitRun, onClickRefreshAllAction })
</script>

<template>
  <div class="case-som-wrapper case-form-wrapper">
    <GpForm ref="somFormRef" layout="vertical" :options="somConfig.somFormOptions" class="gp__grid-three" />
    <div class="gp__grid-half">
      <div class="chart-box">
        <a-card title="Raw SOM">
          <a-spin tip="loading..." :spinning="somRawLoading">
            <GpChart id="case1Heat" :width="chartWidth" :height="chartHeight" :options="heatRawOptions" />
          </a-spin>
        </a-card>
      </div>
      <div class="chart-box">
        <a-card title="2D SOM">
          <template #extra>
            <div class="select-wrapper" style="margin-right: 10px;">
              <span>Cluster: </span>
              <a-select
                v-model:value="clusterName"
                size="small"
                style="width: 100px;margin-left: 5px;"
                allow-clear
                :options="clusterOptions"
                @change="onClickClusterName"
              />
            </div>
            <div class="select-wrapper">
              <span>Type: </span>
              <a-select
                v-model:value="varName"
                size="small"
                style="width: 100px;margin-left: 5px;"
                :options="varNameOptions"
                @change="onClickChangeHeatmap"
              />
            </div>
          </template>
          <a-spin tip="loading..." :spinning="somRawLoading">
            <GpChart id="case2Heat" :width="chartWidth" :height="chartHeight" :options="heat2DOptions" />
          </a-spin>
        </a-card>
      </div>
    </div>
  </div>
</template>

<style lang="less" scoped>
@import url('../../common.less');
</style>
